package com.yc.cloud.admin.service.impl;

import com.yc.cloud.common.orm.BaseEntity;
import com.yc.cloud.common.orm.CommonPage;
import com.yc.cloud.common.basic.dto.BasePageReqDTO;
import com.yc.cloud.admin.dto.request.AlgStrategyRuleCreateReqDTO;
import com.yc.cloud.admin.dto.request.AlgStrategyRuleQueryReqDTO;
import com.yc.cloud.admin.dto.request.AlgStrategyRuleUpdateReqDTO;
import com.yc.cloud.admin.vo.AlgStrategyRuleVo;
import com.yc.cloud.entity.AlgAlgorithm;
import com.yc.cloud.entity.AlgModel;
import com.yc.cloud.entity.AlgModelVersion;
import com.yc.cloud.entity.AlgStrategyRule;
import com.yc.cloud.mapper.AlgStrategyRuleMapper;
import com.yc.cloud.admin.service.AlgAlgorithmService;
import com.yc.cloud.admin.service.AlgModelService;
import com.yc.cloud.admin.service.AlgModelVersionService;
import com.yc.cloud.admin.service.AlgStrategyRuleService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yc.cloud.common.basic.exception.Asserts;
import com.yc.cloud.api.enums.PublishStatusEnum;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Objects;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 算法策略规则表 服务实现类
 * </p>
 *
 * @author kinggu
 * @since 2025-07-30
 */
@Service
public class AlgStrategyRuleServiceImpl extends ServiceImpl<AlgStrategyRuleMapper, AlgStrategyRule> implements AlgStrategyRuleService {

    @Autowired
    private AlgAlgorithmService algAlgorithmService;
    
    @Autowired
    private AlgModelService algModelService;
    
    @Autowired
    private AlgModelVersionService algModelVersionService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AlgStrategyRuleVo create(AlgStrategyRuleCreateReqDTO createReqDTO) {
        // 1. 检查同一策略下是否已存在相同算法的规则
        if (checkAlgorithmRuleExists(createReqDTO.getStrategyId(), createReqDTO.getAlgAlgorithmId(), null)) {
            Asserts.fail("该策略下已存在此算法的规则，请勿重复添加");
        }
        
        // 2. 创建实体并保存
        AlgStrategyRule entity = new AlgStrategyRule();
        BeanUtils.copyProperties(createReqDTO, entity);
        // 默认设置为未发布状态
        entity.setPublishStatus(PublishStatusEnum.UNPUBLISHED.getValue());
        boolean success = save(entity);
        if (success) {
            return getVOById(entity.getId());
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AlgStrategyRuleVo update(AlgStrategyRuleUpdateReqDTO updateReqDTO) {
        // 1. 检查记录是否存在
        AlgStrategyRule entity = get(updateReqDTO.getId());
        if (entity == null) {
            Asserts.fail("策略规则不存在");
            return null;
        }

        // 2. 检查更新后的规则是否与其它规则冲突
        if (checkAlgorithmRuleExists(updateReqDTO.getStrategyId(), updateReqDTO.getAlgAlgorithmId(), updateReqDTO.getId())) {
            Asserts.fail("该策略下已存在此算法的规则，请勿重复添加");
        }

        // 3. 复制属性并更新
        BeanUtils.copyProperties(updateReqDTO, entity);
        boolean success = updateById(entity);
        if (success) {
            return getVOById(entity.getId());
        }
        return null;
    }

    @Override
    public CommonPage<AlgStrategyRuleVo> list(BasePageReqDTO pageReqDTO) {
        // 调用新的方法，保持向后兼容
        if (pageReqDTO instanceof AlgStrategyRuleQueryReqDTO) {
            return list((AlgStrategyRuleQueryReqDTO) pageReqDTO);
        }
        
        AlgStrategyRuleQueryReqDTO queryReqDTO = new AlgStrategyRuleQueryReqDTO();
        BeanUtils.copyProperties(pageReqDTO, queryReqDTO);
        return list(queryReqDTO);
    }
    
    @Override
    public CommonPage<AlgStrategyRuleVo> list(AlgStrategyRuleQueryReqDTO queryReqDTO) {
        QueryWrapper<AlgStrategyRule> queryWrapper = new QueryWrapper<>();
        
        // 1. 添加筛选条件
        if (queryReqDTO.getStrategyId() != null) {
            queryWrapper.eq(AlgStrategyRule.StrategyId, queryReqDTO.getStrategyId());
        }
        
        // 2. 排序
        if (StrUtil.isNotEmpty(queryReqDTO.getSortBy())) {
            if (Objects.equals(BasePageReqDTO.ORDER_DESC, queryReqDTO.getOrder())) {
                queryWrapper.orderByDesc(StrUtil.toUnderlineCase(queryReqDTO.getSortBy()));
            } else {
                queryWrapper.orderByAsc(StrUtil.toUnderlineCase(queryReqDTO.getSortBy()));
            }
        } else {
            // 默认按创建时间倒序
            queryWrapper.orderByDesc(BaseEntity.CREATE_TIME);
        }
        
        // 3. 关键字模糊查询
        if (StrUtil.isNotEmpty(queryReqDTO.getKeyword())) {
            queryWrapper.and(wrapper -> wrapper.like(AlgStrategyRule.ParamConfig, queryReqDTO.getKeyword()));
        }
        
        // 4. 分页查询
        CommonPage<AlgStrategyRuleVo> result;
        if (Boolean.TRUE.equals(queryReqDTO.getPage())) {
            Page<AlgStrategyRule> page = new Page<>(queryReqDTO.getPageNum(), queryReqDTO.getPageSize());
            Page<AlgStrategyRule> dbPage = baseMapper.selectPage(page, queryWrapper);
            result = CommonPage.restPage(dbPage.convert(this::convertToVo));
        } else {
            List<AlgStrategyRule> allRecords = baseMapper.selectList(queryWrapper);
            result = new CommonPage<>();
            result.setList(convertToVoList(allRecords));
            result.setTotal((long) allRecords.size());
            result.setPageNum(1);
            result.setPageSize(allRecords.size());
            result.setTotalPage(1);
        }
        
        return result;
    }

    @Override
    public AlgStrategyRuleVo getVOById(Long id) {
        AlgStrategyRule entity = getById(id);
        return convertToVo(entity);
    }

    @Override
    public List<AlgStrategyRuleVo> convertToVoList(List<AlgStrategyRule> entityList) {
        if (entityList == null) {
            return null;
        }
        return entityList.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publish(Long id) {
        // 1. 获取要发布的规则
        AlgStrategyRule rule = getById(id);
        if (rule == null) {
            Asserts.fail("策略规则不存在");
            return false;
        }

        // 2. 检查规则的完整性
        if (rule.getAlgModelVersionId() == null) {
            Asserts.fail("策略规则未绑定模型版本，无法发布");
            return false;
        }

        // 3. 将同一策略下其它规则全部置为未发布（客户端只能使用一个规则）
        AlgStrategyRule unpublishUpdate = new AlgStrategyRule();
        unpublishUpdate.setPublishStatus(PublishStatusEnum.UNPUBLISHED.getValue());
        baseMapper.update(
                unpublishUpdate,
                new QueryWrapper<AlgStrategyRule>()
                        .eq(AlgStrategyRule.StrategyId, rule.getStrategyId())
                        .ne(AlgStrategyRule.ID, id)
                        .eq(AlgStrategyRule.PublishStatus, PublishStatusEnum.PUBLISHED.getValue())
        );

        // 4. 设置当前规则为已发布
        rule.setPublishStatus(PublishStatusEnum.PUBLISHED.getValue());
        return updateById(rule);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unpublish(Long id) {
        // 1. 获取要取消发布的规则
        AlgStrategyRule rule = getById(id);
        if (rule == null) {
            Asserts.fail("策略规则不存在");
            return false;
        }

        // 2. 检查当前状态
        if (!PublishStatusEnum.isPublished(rule.getPublishStatus())) {
            // 已经是未发布状态，直接返回成功
            return true;
        }

        // 3. 设置为未发布状态
        rule.setPublishStatus(PublishStatusEnum.UNPUBLISHED.getValue());
        return updateById(rule);
    }

    private AlgStrategyRuleVo convertToVo(AlgStrategyRule entity) {
        if (entity == null) {
            return null;
        }
        AlgStrategyRuleVo vo = new AlgStrategyRuleVo();
        BeanUtils.copyProperties(entity, vo);
        
        // 填充算法名称
        if (entity.getAlgAlgorithmId() != null) {
            AlgAlgorithm algorithm = algAlgorithmService.getById(entity.getAlgAlgorithmId());
            if (algorithm != null) {
                vo.setAlgorithmName(algorithm.getName());
            }
        }
        
        // 填充模型版本信息
        if (entity.getAlgModelVersionId() != null) {
            AlgModelVersion modelVersion = algModelVersionService.getById(entity.getAlgModelVersionId());
            if (modelVersion != null) {
                vo.setModelVersion(modelVersion.getModelVersion());
                
                // 获取模型名称
                if (modelVersion.getModelId() != null) {
                    AlgModel model = algModelService.getById(modelVersion.getModelId());
                    if (model != null) {
                        vo.setModelName(model.getName());
                    }
                }
            }
        }
        
        return vo;
    }

    @Override
    public AlgStrategyRule get(Long id) {
        return getById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        // 1. 校验待删除的记录是否存在
        if (getById(id) == null) {
            Asserts.fail("记录不存在，无法删除");
        }
        return removeById(id);
    }

    /**
     * 检查在指定策略下，是否已存在针对某个算法的规则
     *
     * @param strategyId     策略ID
     * @param algAlgorithmId 算法ID
     * @param excludeId      需要排除的规则ID (用于更新检查)
     * @return true 如果存在，false 如果不存在
     */
    private boolean checkAlgorithmRuleExists(Long strategyId, Long algAlgorithmId, Long excludeId) {
        QueryWrapper<AlgStrategyRule> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(AlgStrategyRule.StrategyId, strategyId)
                    .eq(AlgStrategyRule.AlgAlgorithmId, algAlgorithmId);
        if (excludeId != null) {
            queryWrapper.ne(BaseEntity.ID, excludeId);
        }
        return this.count(queryWrapper) > 0;
    }
} 